package com.docmgmt.mvp.service;

import com.docmgmt.mvp.dto.*;
import com.docmgmt.mvp.entity.FolderEntity;
import com.docmgmt.mvp.exception.BusinessException;
import com.docmgmt.mvp.mapper.FolderMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 文件夹服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FolderService {

    private final FolderMapper folderMapper;

    /**
     * 创建文件夹
     *
     * @param request 创建请求
     * @param userId  用户ID
     * @return 文件夹VO
     */
    @Transactional
    public FolderVO createFolder(CreateFolderRequest request, Long userId) {
        log.info("创建文件夹: name={}, parentId={}, userId={}",
                request.getName(), request.getParentId(), userId);

        // 1. 参数校验
        Long parentId = request.getParentId() != null ? request.getParentId() : 0L;

        // 2. 检查父文件夹是否存在（如果不是根目录）
        String parentPath = "/";
        if (parentId > 0) {
            FolderEntity parent = folderMapper.selectById(parentId);
            if (parent == null || parent.getIsDeleted()) {
                throw new BusinessException("父文件夹不存在");
            }
            parentPath = parent.getPath();
        }

        // 3. 计算新文件夹的完整路径
        String newPath = calculatePath(parentPath, request.getName());

        // 4. 检查同名文件夹是否已存在
        FolderEntity existing = folderMapper.findByPath(newPath);
        if (existing != null) {
            throw new BusinessException("同名文件夹已存在");
        }

        // 5. 计算层级
        int level = parentId == 0 ? 1 : (parentPath.split("/").length);

        // 6. 创建文件夹实体
        LocalDateTime now = LocalDateTime.now();
        FolderEntity folder = FolderEntity.builder()
                .name(request.getName())
                .parentId(parentId)
                .path(newPath)
                .level(level)
                .description(request.getDescription())
                .creatorId(userId)
                .ownerId(userId)
                .sortOrder(0)
                .folderType("shared")  // v3.0: 默认为shared类型
                .defaultPrivacy("shared")  // v3.0: 默认隐私级别为shared
                .isDeleted(false)
                .createdAt(now)
                .updatedAt(now)
                .build();

        // 7. 保存到数据库
        folderMapper.insert(folder);
        log.info("文件夹创建成功: id={}, path={}", folder.getId(), folder.getPath());

        // 8. 返回VO
        return entityToVO(folder);
    }

    /**
     * 更新文件夹
     *
     * @param folderId 文件夹ID
     * @param request  更新请求
     * @param userId   用户ID
     * @return 文件夹VO
     */
    @Transactional
    public FolderVO updateFolder(Long folderId, UpdateFolderRequest request, Long userId) {
        log.info("更新文件夹: id={}, userId={}", folderId, userId);

        // 1. 查询文件夹
        FolderEntity folder = getFolderById(folderId);

        // 2. 权限检查（简化版：只有创建者和所有者可以修改）
        if (!folder.getCreatorId().equals(userId) && !folder.getOwnerId().equals(userId)) {
            throw new BusinessException("无权限修改此文件夹");
        }

        // 3. 更新字段
        boolean needUpdatePath = false;
        String oldPath = folder.getPath();

        if (request.getName() != null && !request.getName().equals(folder.getName())) {
            // 重命名需要更新路径
            String parentPath = "/";
            if (folder.getParentId() > 0) {
                FolderEntity parent = folderMapper.selectById(folder.getParentId());
                parentPath = parent.getPath();
            }
            String newPath = calculatePath(parentPath, request.getName());

            // 检查新路径是否已存在
            FolderEntity existing = folderMapper.findByPath(newPath);
            if (existing != null && !existing.getId().equals(folderId)) {
                throw new BusinessException("同名文件夹已存在");
            }

            folder.setName(request.getName());
            folder.setPath(newPath);
            needUpdatePath = true;
        }

        if (request.getDescription() != null) {
            folder.setDescription(request.getDescription());
        }

        // v3.0: 支持修改文件夹类型和默认隐私级别
        if (request.getFolderType() != null) {
            folder.setFolderType(request.getFolderType());
        }
        if (request.getDefaultPrivacy() != null) {
            folder.setDefaultPrivacy(request.getDefaultPrivacy());
        }

        folder.setUpdatedAt(LocalDateTime.now());

        // 4. 保存更新
        folderMapper.updateById(folder);

        // 5. 如果路径变化，级联更新子文件夹路径
        if (needUpdatePath) {
            updateSubfolderPaths(oldPath, folder.getPath());
        }

        log.info("文件夹更新成功: id={}", folderId);
        return entityToVO(folder);
    }

    /**
     * 删除文件夹（软删除）
     *
     * @param folderId 文件夹ID
     * @param userId   用户ID
     */
    @Transactional
    public void deleteFolder(Long folderId, Long userId) {
        log.info("删除文件夹: id={}, userId={}", folderId, userId);

        // 1. 查询文件夹
        FolderEntity folder = getFolderById(folderId);

        // 2. 权限检查
        if (!folder.getCreatorId().equals(userId) && !folder.getOwnerId().equals(userId)) {
            throw new BusinessException("无权限删除此文件夹");
        }

        // 3. 检查是否有子文件夹或文件
        int subfolderCount = folderMapper.countSubfolders(folderId);
        int fileCount = folderMapper.countFiles(folderId);

        if (subfolderCount > 0 || fileCount > 0) {
            throw new BusinessException("文件夹不为空，无法删除");
        }

        // 4. 软删除
        folder.setIsDeleted(true);
        folder.setDeletedAt(LocalDateTime.now());
        folder.setDeletedBy(userId);
        folder.setUpdatedAt(LocalDateTime.now());
        folderMapper.updateById(folder);

        log.info("文件夹删除成功: id={}", folderId);
    }

    /**
     * 移动文件夹
     *
     * @param folderId 文件夹ID
     * @param request  移动请求
     * @param userId   用户ID
     * @return 文件夹VO
     */
    @Transactional
    public FolderVO moveFolder(Long folderId, MoveFolderRequest request, Long userId) {
        log.info("移动文件夹: id={}, targetParentId={}, userId={}",
                folderId, request.getTargetParentId(), userId);

        // 1. 查询源文件夹
        FolderEntity folder = getFolderById(folderId);

        // 2. 权限检查
        if (!folder.getCreatorId().equals(userId) && !folder.getOwnerId().equals(userId)) {
            throw new BusinessException("无权限移动此文件夹");
        }

        // 3. 检查目标父文件夹
        Long targetParentId = request.getTargetParentId();
        String targetParentPath = "/";

        if (targetParentId > 0) {
            FolderEntity targetParent = folderMapper.selectById(targetParentId);
            if (targetParent == null || targetParent.getIsDeleted()) {
                throw new BusinessException("目标父文件夹不存在");
            }
            targetParentPath = targetParent.getPath();

            // 防止移动到自己的子文件夹
            if (targetParentPath.startsWith(folder.getPath() + "/")) {
                throw new BusinessException("不能移动到自己的子文件夹");
            }
        }

        // 4. 如果目标父文件夹与当前父文件夹相同，无需移动
        if (folder.getParentId().equals(targetParentId)) {
            throw new BusinessException("文件夹已在目标位置");
        }

        // 5. 计算新路径
        String oldPath = folder.getPath();
        String newPath = calculatePath(targetParentPath, folder.getName());

        // 检查新路径是否已存在
        FolderEntity existing = folderMapper.findByPath(newPath);
        if (existing != null) {
            throw new BusinessException("目标位置已存在同名文件夹");
        }

        // 6. 更新文件夹
        folder.setParentId(targetParentId);
        folder.setPath(newPath);
        folder.setUpdatedAt(LocalDateTime.now());
        folderMapper.updateById(folder);

        // 7. 级联更新子文件夹路径
        updateSubfolderPaths(oldPath, newPath);

        log.info("文件夹移动成功: id={}, oldPath={}, newPath={}", folderId, oldPath, newPath);
        return entityToVO(folder);
    }

    /**
     * 获取文件夹列表
     *
     * @param parentId  父文件夹ID
     * @param userId    用户ID
     * @param page      页码
     * @param pageSize  每页数量
     * @param sortBy    排序字段
     * @param sortOrder 排序方向
     * @return 分页结果
     */
    public PagedResult<FolderVO> listFolders(
            Long parentId, Long userId, Integer page, Integer pageSize,
            String sortBy, String sortOrder) {

        log.info("查询文件夹列表: parentId={}, userId={}, page={}, pageSize={}",
                parentId, userId, page, pageSize);

        // 参数默认值
        if (parentId == null) parentId = 0L;
        if (page == null || page < 1) page = 1;
        if (pageSize == null || pageSize < 1) pageSize = 20;
        if (sortBy == null || sortBy.isEmpty()) sortBy = "created_at";
        if (sortOrder == null || !sortOrder.equalsIgnoreCase("asc")) sortOrder = "desc";

        // 查询数据
        List<FolderEntity> entities = folderMapper.listByParentId(
                parentId, userId, sortBy, sortOrder);

        // 手动分页
        int total = entities.size();
        int start = (page - 1) * pageSize;
        int end = Math.min(start + pageSize, total);
        List<FolderEntity> pagedEntities = (start < total) ?
                entities.subList(start, end) : List.of();

        // 转换为VO
        List<FolderVO> items = pagedEntities.stream()
                .map(this::entityToVO)
                .collect(Collectors.toList());

        // 构造分页响应
        return PagedResult.<FolderVO>builder()
                .items(items)
                .pagination(PagedResult.Pagination.builder()
                        .page(page)
                        .pageSize(pageSize)
                        .total((long) total)
                        .totalPages((int) Math.ceil((double) total / pageSize))
                        .build())
                .build();
    }

    /**
     * 获取文件夹树
     *
     * @param userId 用户ID
     * @return 文件夹树列表
     */
    public List<FolderVO> getFolderTree(Long userId) {
        log.info("获取文件夹树: userId={}", userId);

        // 1. 查询所有可访问的文件夹
        List<FolderEntity> allFolders = folderMapper.listAccessibleFolders(userId);

        // 2. 构建树形结构
        return buildTree(allFolders);
    }

    /**
     * 根据ID获取文件夹详情
     *
     * @param folderId 文件夹ID
     * @return 文件夹VO
     */
    public FolderVO getFolderDetail(Long folderId) {
        FolderEntity folder = getFolderById(folderId);
        return entityToVO(folder);
    }

    /**
     * 根据ID获取文件夹实体（内部方法）
     */
    private FolderEntity getFolderById(Long folderId) {
        FolderEntity folder = folderMapper.selectById(folderId);
        if (folder == null || folder.getIsDeleted()) {
            throw new BusinessException("文件夹不存在或已删除");
        }
        return folder;
    }

    /**
     * 计算文件夹路径
     *
     * @param parentPath 父路径
     * @param folderName 文件夹名称
     * @return 完整路径
     */
    private String calculatePath(String parentPath, String folderName) {
        if (parentPath.equals("/")) {
            return "/" + folderName;
        } else {
            return parentPath + "/" + folderName;
        }
    }

    /**
     * 级联更新子文件夹路径
     *
     * @param oldPath 旧路径
     * @param newPath 新路径
     */
    private void updateSubfolderPaths(String oldPath, String newPath) {
        int count = folderMapper.updateSubfolderPaths(oldPath, newPath);
        log.info("更新了 {} 个子文件夹的路径", count);
    }

    /**
     * 构建文件夹树
     *
     * @param allFolders 所有文件夹列表
     * @return 树形结构的文件夹列表
     */
    private List<FolderVO> buildTree(List<FolderEntity> allFolders) {
        // 转换为VO并建立ID索引
        Map<Long, FolderVO> folderMap = new HashMap<>();
        List<FolderVO> rootFolders = new ArrayList<>();

        for (FolderEntity entity : allFolders) {
            FolderVO vo = entityToVO(entity);
            vo.setChildren(new ArrayList<>());
            folderMap.put(entity.getId(), vo);
        }

        // 构建树形结构
        for (FolderEntity entity : allFolders) {
            FolderVO vo = folderMap.get(entity.getId());
            if (entity.getParentId() == 0) {
                // 根文件夹
                rootFolders.add(vo);
            } else {
                // 子文件夹
                FolderVO parent = folderMap.get(entity.getParentId());
                if (parent != null) {
                    parent.getChildren().add(vo);
                }
            }
        }

        return rootFolders;
    }

    /**
     * 实体转VO
     *
     * @param entity 文件夹实体
     * @return 文件夹VO
     */
    private FolderVO entityToVO(FolderEntity entity) {
        // 统计子文件夹和文件数量
        int subfolderCount = folderMapper.countSubfolders(entity.getId());
        int fileCount = folderMapper.countFiles(entity.getId());

        return FolderVO.builder()
                .id(entity.getId())
                .name(entity.getName())
                .parentId(entity.getParentId())
                .path(entity.getPath())
                .level(entity.getLevel())
                .description(entity.getDescription())
                .creatorId(entity.getCreatorId())
                .creatorName("用户" + entity.getCreatorId())  // 简化版，完整版需要关联sys_user表
                .ownerId(entity.getOwnerId())
                .ownerName("用户" + entity.getOwnerId())
                .folderType(entity.getFolderType())  // v3.0: 文件夹类型
                .defaultPrivacy(entity.getDefaultPrivacy())  // v3.0: 默认隐私级别
                .subfolderCount(subfolderCount)
                .fileCount(fileCount)
                .createdAt(entity.getCreatedAt() != null ?
                        entity.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null)
                .updatedAt(entity.getUpdatedAt() != null ?
                        entity.getUpdatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null)
                .build();
    }
}
